package com.time.company.components.compose;

import android.app.Activity;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps2d.AMap;
import com.amap.api.maps2d.MapView;
import com.amap.api.maps2d.model.BitmapDescriptorFactory;
import com.amap.api.maps2d.model.LatLng;
import com.amap.api.maps2d.model.MarkerOptions;
import com.amap.api.maps2d.model.MyLocationStyle;
import com.amap.api.maps2d.overlay.PoiOverlay;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.core.SuggestionCity;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.amap.api.services.poisearch.PoiItemDetail;
import com.amap.api.services.poisearch.PoiResult;
import com.amap.api.services.poisearch.PoiSearch;
import com.time.company.R;
import com.time.company.base.BaseActivity;
import com.time.company.base.BaseFragment;
import com.time.company.components.compose.city.CityListActivity;
import com.time.company.components.dialog.LoadingDialog;
import com.time.company.utils.ToastUtils;
import com.time.company.utils.string.Constant;
import com.yanzhenjie.nohttp.Logger;

import java.util.ArrayList;
import java.util.List;

import static android.view.View.VISIBLE;

/**
 * Created by Bing on 2017/11/3.
 * E-mail is tx16bing@163.com
 */

public class TimeMapActivity extends BaseActivity implements View.OnClickListener
        , AMap.OnMyLocationChangeListener, PoiSearch.OnPoiSearchListener,
        GeocodeSearch.OnGeocodeSearchListener, AMapLocationListener {

    private static final String EXTRA_ENTER_FLAG = "extra_enter_flag";
    private static final String EXTRA_MAP_TITLE = "extra_map_title";
    private static final int CITY_LIST_REQUEST_CODE = 102;
    private String mapTitle;

    // Views
    private TextView tvCurCity;
    private EditText etSearchKey;
    private ImageView ivClear;
    private TextView tvRight;

    private MapView mapView;
    private AMap mMap;
    private TextView tvLocation;
    private ListView lvResult;

    private MyLocationStyle mLocationStyle;
    private double mLatitude, mLongitude;

    // poi
    private LoadingDialog proDialog;
    private PoiResult poiResult; // poi返回的结果
    private int currentPage = 0;// 当前页面，从0开始计数
    private PoiSearch.Query query;// Poi查询条件类
    private PoiSearch poiSearch;// POI搜索
    private PoiListAdapter listAdapter;
    private List<PoiItem> mPoiItems;

    private boolean canSearch;

    public static void start(Activity activity, int requestCode, String flag, String title) {
        Intent intent = new Intent(activity, TimeMapActivity.class);
        intent.putExtra(EXTRA_ENTER_FLAG, flag);
        intent.putExtra(EXTRA_MAP_TITLE, title);
        activity.startActivityForResult(intent, requestCode);
    }

    public static void start(BaseFragment fragment, int requestCode, String flag, String title) {
        Intent intent = new Intent(fragment.mContext, TimeMapActivity.class);
        intent.putExtra(EXTRA_ENTER_FLAG, flag);
        intent.putExtra(EXTRA_MAP_TITLE, title);
        fragment.startActivityForResult(intent, requestCode);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_time_map);
        mapTitle = getIntent().getStringExtra(EXTRA_MAP_TITLE);
        assignViews(savedInstanceState);
        addListener();
        initLocationStyle();
        createLocationRequest();
    }

    private boolean isApply() {
        if (TextUtils.equals(getString(R.string.map_flag_apply), getIntent().getStringExtra(EXTRA_ENTER_FLAG))) {
            return true;
        }

        return false;
    }

    private boolean isHasTitle() {
        if (!TextUtils.isEmpty(mapTitle)) {
            return true;
        }

        return false;
    }

    private void assignViews(Bundle state) {
        tvCurCity = findView(R.id.tv_current_location);
        tvCurCity.setVisibility(isApply() ? VISIBLE : View.GONE);
        etSearchKey = findView(R.id.et_search_key);
        ivClear = findView(R.id.iv_clear);
        tvRight = findView(R.id.tv_right);
        lvResult = findView(R.id.lv_poi_result);

        tvLocation = findView(R.id.tv_time_map_location);
        if (isHasTitle()) {
            tvLocation.setText(getIntent().getStringExtra(EXTRA_MAP_TITLE));
        }
        mapView = findView(R.id.time_map);
        mapView.onCreate(state);
        if (mMap == null) {
            mMap = mapView.getMap();
        }
    }

    private void addListener() {
        tvCurCity.setOnClickListener(this);
        ivClear.setOnClickListener(this);
        tvRight.setOnClickListener(this);
        findView(R.id.btn_poi_confirm).setOnClickListener(this);
        etSearchKey.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (etSearchKey.getText().length() == 0) {
                    ivClear.setVisibility(View.INVISIBLE);
                    canSearch = false;
                } else {
                    ivClear.setVisibility(VISIBLE);
                    canSearch = true;
                }
                tvRight.setText(canSearch ? getString(R.string.btn_search) : getString(R.string.btn_cancel));
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        etSearchKey.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus) {
                    if (!TextUtils.isEmpty(etSearchKey.getText())) {
                        ivClear.setVisibility(VISIBLE);
                        canSearch = true;
                    } else {
                        ivClear.setVisibility(View.INVISIBLE);
                        canSearch = false;
                    }
                } else {
                    ivClear.setVisibility(View.INVISIBLE);
                }
            }
        });
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        //在activity执行onSaveInstanceState时执行mMapView.onSaveInstanceState (outState)，保存地图当前的状态
        mapView.onSaveInstanceState(outState);
    }

    private void initLocationStyle() {
        mLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点，定位点依照设备方向旋转，并且会跟随设备移动。（1秒1次定位）如果不设置myLocationType，默认也会执行此种模式。
        mLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);
        mLocationStyle.showMyLocation(true);
        mLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.iv_map_location_me));
//        mLocationStyle.strokeColor(R.color.colorPrimary);
//        mLocationStyle.radiusFillColor(R.color.colorPrimary);
//        mLocationStyle.interval(5000); //设置连续定位模式下的定位间隔，只在连续定位模式下生效，单次定位模式下不会生效。单位为毫秒。
        mMap.setMyLocationStyle(mLocationStyle);//设置定位蓝点的Style
        mMap.getUiSettings().setMyLocationButtonEnabled(false);//设置默认定位按钮是否显示，非必需设置。
        mMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点，false表示隐藏定位蓝点并不进行定位，默认是false。
        mMap.setOnMyLocationChangeListener(this);
    }

    protected void createLocationRequest() {

        if (!isHasTitle()) {
            tvLocation.setText("定位中...");
        }

        // 初始化请求
        AMapLocationClient locationRequest = new AMapLocationClient(getApplicationContext());

        // 设置回调监听
        locationRequest.setLocationListener(this);

        // 初始化参数集
        AMapLocationClientOption mLocationOption = new AMapLocationClientOption();

        // 高精度定位模式，省电模式， 仅设备模式
        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);

        // 是否返回地址信息
        mLocationOption.setNeedAddress(true);

        // 设置重定位时间间隔
        mLocationOption.setInterval(5000);

        mLocationOption.setOnceLocation(true);

        // 设置参数集
        locationRequest.setLocationOption(mLocationOption);

        locationRequest.startLocation();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {

            case R.id.tv_current_location:
                // 推荐地点列表
                CityListActivity.start(this, CITY_LIST_REQUEST_CODE);
                break;

            case R.id.tv_right:
                // poi search
                if (canSearch) {
                    if (!checkForm())
                        return;
                    doSearchQuery();
                } else {
                    finish();
                }

                break;

            case R.id.iv_clear:
                etSearchKey.setText("");
                break;

            case R.id.btn_poi_confirm:
                Intent intent = new Intent();
                intent.putExtra(Constant.LATITUDE, mLatitude);
                intent.putExtra(Constant.LONGITUDE, mLongitude);
                intent.putExtra(Constant.LOCATION, tvLocation.getText().toString());
                intent.putExtra(Constant.CITY, tvCurCity.getText().toString());
                setResult(RESULT_OK, intent);
                finish();
                break;

            default:
                break;

        }
    }

    private void doSearchQuery() {
        showDialog();
        currentPage = 0;
        // 第一个参数表示搜索字符串，第二个参数表示poi搜索类型，第三个参数表示poi搜索区域（空字符串代表全国）
        query = new PoiSearch.Query(etSearchKey.getText().toString().trim(), "",
                isApply() ? tvCurCity.getText().toString() : "");
        query.setPageSize(10);// 设置每页最多返回多少条poiitem
        query.setPageNum(currentPage);// 设置查第一页

        poiSearch = new PoiSearch(this, query);
        poiSearch.setOnPoiSearchListener(this);
        poiSearch.searchPOIAsyn();
    }

    /**
     * POI信息查询回调方法
     */
    @Override
    public void onPoiSearched(PoiResult result, int rCOde) {
        dismissDialog();
        if (result != null && result.getQuery() != null) {// 搜索poi的结果
            if (result.getQuery().equals(query)) {// 是否是同一条
                poiResult = result;
                // 取得搜索到的poiitems有多少页
                List<PoiItem> poiItems = poiResult.getPois();// 取得第一页的poiitem数据，页数从数字0开始
                List<SuggestionCity> suggestionCities = poiResult
                        .getSearchSuggestionCitys();// 当搜索不到poiitem数据时，会返回含有搜索关键字的城市信息

                if (poiItems != null && poiItems.size() > 0) {
                    mMap.clear();// 清理之前的图标
                    PoiOverlay poiOverlay = new PoiOverlay(mMap, poiItems);
                    poiOverlay.removeFromMap();
                    poiOverlay.addToMap();
                    poiOverlay.zoomToSpan();
                    mPoiItems = poiItems;
                    setPoiAdapter();
                } else if (suggestionCities != null
                        && suggestionCities.size() > 0) {
                    showSuggestCity(suggestionCities);
                } else {
                    ToastUtils.showShort("对不起，没有搜索到相关数据！");
                }
            }
        } else {
            ToastUtils.showShort("对不起，没有搜索到相关数据！");
        }
    }

    /**
     * poi adapter
     */
    private void setPoiAdapter() {
        if (listAdapter == null) {
            listAdapter = new PoiListAdapter(this, mPoiItems);
            lvResult.setAdapter(listAdapter);
            lvResult.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    // TODO: 2017/11/6
                    PoiItem item = (PoiItem) listAdapter.getItem(position);
                    if (null != item) {
                        List<PoiItem> poiItems = new ArrayList<>();
                        poiItems.add(item);
                        mLatitude = item.getLatLonPoint().getLatitude();
                        mLongitude = item.getLatLonPoint().getLongitude();
                        if (isApply()){
                            tvLocation.setText(new StringBuilder()
                                    .append(item.getProvinceName())
                                    .append(item.getCityName())
                                    .append(item.getAdName())
                                    .append(item.getTitle()));
                        }else {
                            tvLocation.setText(item.getTitle());
                        }
                        mMap.clear();
                        PoiOverlay poiOverlay = new PoiOverlay(mMap, poiItems);
                        poiOverlay.removeFromMap();
                        poiOverlay.addToMap();
                        poiOverlay.zoomToSpan();
                        lvResult.setVisibility(View.GONE);
                    }
                }
            });

        } else {
            listAdapter.updateData(mPoiItems);
        }
    }

    /**
     * poi没有搜索到数据，返回一些推荐城市的信息
     */
    private void showSuggestCity(List<SuggestionCity> cities) {
        String infomation = "推荐城市\n";
        for (int i = 0; i < cities.size(); i++) {
            infomation += "城市名称:" + cities.get(i).getCityName() + "城市区号:"
                    + cities.get(i).getCityCode() + "城市编码:"
                    + cities.get(i).getAdCode() + "\n";
        }
        ToastUtils.showLong(infomation);

    }

    @Override
    public void onPoiItemDetailSearched(PoiItemDetail poiItemDetail, int i) {

    }

    /**
     * 显示进度框
     */
    private void showDialog() {
        if (proDialog == null) {
            proDialog = new LoadingDialog(this, "正在搜索:\n" + etSearchKey.getText().toString().trim());
            proDialog.setCancelable(false);
            proDialog.show();
        }
    }

    private void dismissDialog() {
        if (null != proDialog) {
            proDialog.dismiss();
        }
    }

    private boolean checkForm() {
        boolean isFormValid = true;
        if (TextUtils.isEmpty(etSearchKey.getText().toString().trim())) {
            ToastUtils.showShort("请输入搜索关键字");
            isFormValid = false;
        }
        return isFormValid;
    }

    @Override
    public void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mapView.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
    }

    @Override
    public void onMyLocationChange(Location location) {
        // 定位回调
//        if (location == null) {
//            ToastUtils.showShort("定位失败");
//            return;
//        }

//        Logger.i("Current user postion is lat : " + location.getLatitude() +
//                " and lon : " + location.getLongitude());
//        mLatitude = location.getLatitude();
//        mLongitude = location.getLongitude();
//        geocodeSearch(mLatitude, mLongitude);
    }

    @Override
    public void onLocationChanged(AMapLocation aMapLocation) {
        if (aMapLocation == null || aMapLocation.getErrorCode() != 0) {
            ToastUtils.showShort("定位失败");
            return;
        }

        Logger.i("Current user postion is lat : " + aMapLocation.getLatitude() +
                " and lon : " + aMapLocation.getLongitude());
        mLatitude = aMapLocation.getLatitude();
        mLongitude = aMapLocation.getLongitude();
        tvCurCity.setText(aMapLocation.getCity() + "");
        if (!isHasTitle()) {
            tvLocation.setText(aMapLocation.getPoiName());
        }

//        Marker marker = mMap.addMarker(getMarkerOptions(
//                aMapLocation.getLatitude(),
//                aMapLocation.getLongitude(),
//                R.drawable.iv_map_location,
//                aMapLocation.getAddress()));
//        marker.showInfoWindow();
    }

    /**
     * 逆地理编码（坐标转地址）
     *
     * @param mLatitude
     * @param mLongitude
     */
    private void geocodeSearch(double mLatitude, double mLongitude) {
        GeocodeSearch geocodeSearch = new GeocodeSearch(this);
        geocodeSearch.setOnGeocodeSearchListener(this);

        // 第一个参数表示一个Latlng，第二参数表示范围多少米，第三个参数表示是火系坐标系还是GPS原生坐标系
        LatLonPoint latLonPoint = new LatLonPoint(mLatitude, mLongitude);
        RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 200, GeocodeSearch.AMAP);
        geocodeSearch.getFromLocationAsyn(query);
    }

    @Override
    public void onRegeocodeSearched(RegeocodeResult result, int rCode) {
        //解析result获取地址描述信息
        if (null != result.getRegeocodeAddress()) {
            tvCurCity.setText(result.getRegeocodeAddress().getCity());
        }
    }

    @Override
    public void onGeocodeSearched(GeocodeResult result, int rCode) {

    }

    //自定义一个图钉，并且设置图标，当我们点击图钉时，显示设置的信息
    private MarkerOptions getMarkerOptions(double latitude, double longitude, int resId, String markerTip) {
        //设置图钉选项
        MarkerOptions options = new MarkerOptions();
        //图标
        options.icon(BitmapDescriptorFactory.fromResource(resId));
        //位置
        options.position(new LatLng(latitude, longitude));
        StringBuffer buffer = new StringBuffer();
        buffer.append(markerTip);
        //标题
        options.title(buffer.toString());

        return options;

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {

            case CITY_LIST_REQUEST_CODE:
                if (null != data) {
                    String city = data.getStringExtra(CityListActivity.KEY_PICKED_CITY);
                    if (!TextUtils.isEmpty(city)) {
                        tvCurCity.setText(city);
                    }
                }
                break;

            default:
                break;

        }
    }
}
